# special_handlers.py

from item_attribute import *
from gui_maker import *
import new
import ldb_tools
import re

SPECIAL_ATTR_TABLE = {}

def register_special_handler(attr_name, handler, handler_name = None):
    if not handler_name:
        handler_name = handler.func_name
    if not attr_name in SPECIAL_ATTR_TABLE:
        SPECIAL_ATTR_TABLE[attr_name] = {handler_name : handler}
    else:
        if handler_name in SPECIAL_ATTR_TABLE[attr_name]:
            print 'handler %s is updated' % handler_name
        SPECIAL_ATTR_TABLE[attr_name][handler_name] = handler
        
def is_special_attribute(name):
    return name in SPECIAL_ATTR_TABLE

def get_attribute_handlers(attr):
    attr_name = attr.name
    instance_handlers = []
    for handler_name, handler in SPECIAL_ATTR_TABLE[attr_name].items():
        instance_handler = new.instancemethod(handler, attr, ItemAttribute)
        instance_handlers.append((handler_name, instance_handler))
    return instance_handlers

# create detail dialog box
# bind attr to dialogbox

def radio_dialog_box(self):
    dlg = DialogBox(self.name)
    dlg.grid()
  
    
    select_val = IntVar(dlg.root)
    specs = get_specfication(self.name)
    row = 0
    
    def on_change_radio():
        val = select_val.get()
        getattr(self.host, self.name).set(unicode(val))

    count = 0
    column = 0
    for name, val in specs:
        count += 1
        btn = Radiobutton(dlg.root, text = name, value = int(val), variable = select_val, command = on_change_radio)
        btn.grid(row = row, column = column, padx = 3, pady = 3, sticky = W)
        btn['font'] = ('SimSun', 12)
        column += 1
        if count % 3 == 0:
            row += 1
            column = 0

    # select the init state
    cur = getattr(self.host, self.name).get()
    if cur:
        select_val.set(int(cur))
    dlg.mainloop()

def check_dialog_box(self):
    panel = Panel()
    panel.master.title(self.name)

    total_check_val = IntVar(panel)
    pairs = get_specfication(self.name)
    g = CheckGroupMaker(panel, pairs, total_check_val, 2)
    panel.mainloop()

    host_val = getattr(self.host, self.name)
    link_variables(host_val, total_check_val)
    cur = host_val.get()
    
    if cur:
        total_check_val.set(int(cur))
    
    
#
s = """
type
job
loc
view

usescript
equipscript
"""

SPECIAL_LIST = [ (u'type', radio_dialog_box),
                 (u'view', radio_dialog_box),
                 (u'job' , radio_dialog_box),
                 (u'loc' , check_dialog_box),]

for name, handler in SPECIAL_LIST:
    register_special_handler(name, handler, 'create_detail_dialogbox')

class DialogBox(Frame):

    def __init__(self,  title):
        self.root = root = Tk()
        root.title(title)
        Frame.__init__(self, root)

class SpecParser():

    CommentPattern = re.compile(ur'//.+')
    TagPattern = re.compile(ur'<(?P<tagname>\w+)>(?P<data>.+?)</(?P=tagname)>', re.DOTALL | re.I)
    CONTENT_PATTERN = re.compile(ur'\s*(?P<entry_name>[^\s=]+)\s*=\s*(?P<entry_val>[^\s]+)')
    def __init__(self, path):

        self.path = path
        
    def parse(self):
        self.specs = {}
        data = ldb_tools.input_utf16_text_file(self.path).read()
        # remove comment
        data = self.CommentPattern.sub('', data)
        # parse content
        for tagname, content in self.TagPattern.findall(data):
            tagname = tagname.lower()
            assert not tagname in self.specs
            self.specs[tagname] = []
            for line in content.split(u'\r\n'):
                line = line.strip()
                if not line:
                    continue
                m = self.CONTENT_PATTERN.match(line)
                if m:
                    self.specs[tagname].append(m.groups())
            
        
    def get(self, name):
        return self.specs[name]

    def has_spec(self, name):
        return name in self.specs

# add current path?
SPEC_PARSER = SpecParser(r'item_db_spec.txt')
try:
    SPEC_PARSER.parse()
except ParseError:
    print 'parse specification failed!'
    raise
    
def get_specfication(name):
    if not SPEC_PARSER.has_spec(name):
        raise ValueError('%s specification not exist' % name)
    return SPEC_PARSER.get(name)
    

def test():
    dlg = DialogBox('123')
    i = IntVar()
    btn = Radiobutton(dlg, text = '1', value = 1, variable = i)
    btn.grid(row = 0)
    btn = Radiobutton(dlg, text = '2', value = 2, variable = i)
    btn.grid(row = 1)
    i.set(1)
    dlg.grid()
    dlg.mainloop()

if __name__ == '__main__':
    from item_editor import test
    test()
    
